package com.hhkj.admin.student.service.biz.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.hhkj.admin.course.common.cont.CourseConst;
import com.hhkj.admin.course.domain.Course;
import com.hhkj.admin.course.model.req.CourseReq;
import com.hhkj.admin.course.service.extend.CourseExtendService;
import com.hhkj.admin.student.common.cont.StudentBatchConst;
import com.hhkj.admin.student.common.extend.StudentExcelModel;
import com.hhkj.admin.student.common.utils.StudentUtils;
import com.hhkj.admin.student.domain.Student;
import com.hhkj.admin.student.domain.StudentBatch;
import com.hhkj.admin.student.domain.StudentCourse;
import com.hhkj.admin.student.model.dopo.StudentCoursePo;
import com.hhkj.admin.student.model.dopo.StudentDo;
import com.hhkj.admin.student.model.dopo.StudentPo;
import com.hhkj.admin.student.model.req.StudentReq;
import com.hhkj.admin.student.model.res.StudentExclRes;
import com.hhkj.admin.student.model.res.StudentRes;
import com.hhkj.admin.student.service.base.StudentBatchService;
import com.hhkj.admin.student.service.base.StudentCourseService;
import com.hhkj.admin.student.service.base.StudentService;
import com.hhkj.admin.student.service.biz.StudentBizService;
import com.hhkj.admin.student.service.extend.StudentExtendService;
import com.ruoyi.common.base.biz.service.biz.BaseBizServiceImpl;
import com.hhkj.admin.student.common.cont.StudentConst;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.exception.excel.ExcelImportException;
import com.ruoyi.common.model.excel.res.ExcelImportErrorData;
import com.ruoyi.common.model.excel.res.ExcelImportRes;
import com.ruoyi.common.utils.QrUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.excl.model.ImportErrorInfo;
import com.ruoyi.common.utils.excl.utils.ExcelUtils;
import com.ruoyi.common.utils.excl.workbook.*;
import com.ruoyi.system.domain.dto.StudentDto;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 学员信息BizService接口
 *
 * @author ruoyi
 * @since 2023-06-08
 */
@Slf4j
@Service
public class StudentBizServiceImpl
        extends BaseBizServiceImpl<Student, StudentReq, StudentRes, StudentDo, StudentPo, StudentService, StudentExtendService>
        implements StudentBizService
{
    @Autowired
    private StudentService studentService;
    @Autowired
    private StudentBatchService batchService;
    @Autowired
    private StudentCourseService studentCourseService;
    @Autowired
    private StudentExtendService studentExtendService;
    @Autowired
    private CourseExtendService courseExtendService;
    @Autowired
    private SysUserMapper userMapper;

    /**
     * 查询学员信息
     *
     * @param studentReq 学员信息主键
     * @return 学员信息
     */
    @Override
    public StudentRes selectStudentById(StudentReq studentReq)
    {
        List<StudentPo> students = studentCourseService.selectStudentRelevancyList(studentReq);
        if (students.size() == 0) {
            throw new GlobalException("未找到该学员");
        }
        StudentRes studentRes = new StudentRes();
        BeanUtil.copyProperties(students.get(0), studentRes);
        return studentRes;
    }

    /**
     * 查询学员信息列表
     *
     * @param studentReq 学员信息
     * @return 学员信息
     */
    @Override
    public List<StudentPo> selectStudentList(StudentReq studentReq)
    {
        return studentExtendService.selectStudentList(studentReq);
    }


    /**
     * 修改学员信息
     *
     * @param studentReq
     * @return
     */
    @Override
    public boolean update(StudentReq studentReq)
    {
        //检查身份证号码是否重复
        long count = studentService.count(Wrappers.<Student>lambdaQuery()
                .eq(Student::getIdCard, studentReq.getIdCard())
                .ne(Student::getId, studentReq.getId()));
        if (count > 0) {
            throw new GlobalException("身份证号码重复！");
        }
        //更改对应关联的数据
        StudentCourse studentCourse = new StudentCourse();
        studentCourse.setLineDate(studentReq.getLineDate());
        studentCourse.setStatus(studentReq.getStatus());
        studentCourse.setCourseId(studentReq.getCourseId());
        studentCourseService.update(studentCourse, Wrappers.<StudentCourse>lambdaQuery()
                .eq(StudentCourse::getId, studentReq.getConCourseId()));
        //更改student，
        Student student = studentService.getById(studentReq.getId());
        if (!student.getIdCard().equals(studentReq.getIdCard())) {
            StudentUtils.encryptPassword(studentReq);
        }
        return studentService.updateById(studentReq);
    }

    /**
     * 批量删除学员信息
     *
     * @param idList 需要删除的学员信息主键
     * @return 结果
     */
    @Override
    public boolean removeStudentByIdList(List<Long> idList)
    {
        //先判断是否通过审核，已通过审核的不允许删除
        long count = studentCourseService.count(Wrappers.<StudentCourse>lambdaQuery()
                .eq(StudentCourse::getStatus, StudentConst.AuditCode.STATUS_PASS.getCode())
                .in(StudentCourse::getId, idList));
        if (count > 0) {
            throw new GlobalException("存在已审核通过学员，无法删除");
        }
        //删除关联数据
        return studentCourseService.remove(Wrappers.<StudentCourse>lambdaQuery().in(StudentCourse::getId, idList));
    }

    /**
     * 获取学员导入模板
     *
     * @return 请求信息
     */
    @Override
    public Workbook getStudentTemp()
    {
        List<StudentExcelModel> excelModelList = new ArrayList<>();
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(StudentExcelModel.EXCEL_TITLE, StudentExcelModel.EXCEL_NAME), StudentExcelModel.class, excelModelList);
        supplyStudentTemp(workbook);
        return workbook;
    }

    /**
     * 补充学员导入的模板信息
     *
     * @param template 模板信息
     */
    private void supplyStudentTemp(Workbook template)
    {
        //1.表头说明
        Sheet firstSheet = SheetUtils.getFirstSheet(template);
        Row firstRow = RowUtils.getFirstRow(firstSheet);
        Cell titleCell = CellUtils.getFirstCell(firstRow);
        // 设置标题行高
        CellUtils.wrapText(template, titleCell);
        RowUtils.setHeight(firstRow, StudentExcelModel.TITLE_HEIGHT);
        //标题字体格式
        Font titleFont = FontUtils.createFont(template, StudentExcelModel.EXCEL_NAME_FONT_HEIGHT, true, Font.COLOR_RED);
        CellUtils.updatePartContentFont(titleCell, titleFont, StudentExcelModel.EXCEL_NAME);
        //必填字段标红
        SheetUtils.updateRequiredHeaderStyle(template, template.getSheetAt(0), 1, StudentExcelModel.class);

        //2.身份证、手机号单元格设置为文本 2024/1/23 备注设为文本
        CellUtils.setTextCell(template, 4);
        CellUtils.setTextCell(template, 1);
        CellUtils.setTextCell(template, 2);
        //3.课程科目
        // 2023年6月9日 用户在表格中直接选择科目
        Course course = new Course();
        course.setLevelNum(CourseConst.LEVEL_NUM_THIRD);
        course.setDisableFlag(0);
        List<Course> courseList = courseExtendService.listPoAllCourseByDo(course);
        List<String> courseName = courseList.stream().map(Course::getName).collect(Collectors.toList());
        if (courseName.size() > 0) {
            WorkbookUtils.selectHiddenList(template, ArrayUtil.toArray(courseName, String.class), 2, 3, "课程科目");
        }
        //4.到期日期格式
//        CellUtils.setDataColumn(template, 4);
    }

    /**
     * 表格导入
     *
     * @param file 文件
     * @return
     */
    @Override
    public ExcelImportRes importExcl(MultipartFile file)
    {
        //解析表格
        List<StudentExcelModel> studentExcelModels
                = ExcelUtils.importExcel(file, 1, 1, StudentExcelModel.class);
        //获取课程-结构名map
//        Map<String, Course> courseIdNameMap = getCourseIdStructureNameMap();
        Map<String, List<Course>> nameCourseMap = getNameCourseMap();
        //查询数据库中相同身份证的学员
        List<StudentCourse> studentByIdCard = getStudentByIdCard(studentExcelModels);

//        List<ImportErrorInfo> errorResList = Lists.newArrayList();
        List<ExcelImportErrorData> excelImportErrorDataList = new ArrayList<>();
        List<String> idCardListInExcl = Lists.newArrayList();
        List<Student> students = Lists.newArrayList();
        int count = 2;
        for (StudentExcelModel studentExcelModel : studentExcelModels) {
            count++;
            if ("{}".equals(JSON.toJSONString(studentExcelModel))) {
                continue;
            }
            //清除文本首尾空格
            cleanBlank(studentExcelModel);
            //科目名称转为id
            // 2023年6月9日 改为用户在表格中直接选择具体科目，导入时查询多个默认取第一个
            changeCourseNameToId(studentExcelModel, nameCourseMap);
            //检查数据正确性
            checkStudentDataRight(studentExcelModel, idCardListInExcl, students, studentByIdCard, excelImportErrorDataList, count);
        }
        // 给正确数据补充信息
//        applyStudentData(students);
        if (excelImportErrorDataList.size() == 0) {
            saveStudentInfo(students);
        } else {
            throw new ExcelImportException(students.size(), excelImportErrorDataList);
        }
        return new ExcelImportRes(students.size());
    }

    /**
     * 查询数据库中相同身份证的学员
     *
     * @param studentExcelModels 表格数据
     */
    private List<StudentCourse> getStudentByIdCard(List<StudentExcelModel> studentExcelModels)
    {
        //查询数据库中相同身份证的学员
        List<String> statusList = new ArrayList<String>(2);
        statusList.add(StudentConst.AuditCode.STATUS_PASS.getCode());
//        statusList.add(StudentConst.AuditCode.STATUS_NO_CHECK.getCode());
        List<String> idCards = studentExcelModels.stream().map(StudentExcelModel::getIdCard).collect(Collectors.toList());
        StudentCoursePo coursePo = new StudentCoursePo();
        coursePo.setIdCardList(idCards);
        coursePo.setStatusList(statusList);
        return studentCourseService.listStudentCoursePoByDo(coursePo);
    }

    /**
     * 查询全部的科目名称，并转化为map
     *
     * @return 科目名称-科目 map
     */
    private Map<String, List<Course>> getNameCourseMap()
    {
        Course course = new Course();
        course.setLevelNum(CourseConst.LEVEL_NUM_THIRD);
        course.setDisableFlag(0);
        List<Course> courseList = courseExtendService.listPoAllCourseByDo(course);
        //处理为map
        Map<String, List<Course>> nameCourseMap = new HashMap<String, List<Course>>();
        if (courseList != null && courseList.size() > 0) {
            //中文括号转英文
            for (Course course1 : courseList) {
                course1.setName(course1.getName().replace("（", "(").replace("）", ")"));
            }
            nameCourseMap = courseList.stream().collect(Collectors.groupingBy(Course::getName));
        }
        return nameCourseMap;
    }

    /**
     * 获取课程-结构名map
     *
     * @return 科目id-科目结构名map
     */
    private Map<String, Course> getCourseIdStructureNameMap()
    {
        //处理科目
        List<Course> courseList = courseExtendService.listAllWithStructureName();
        Map<String, Course> structureNameCourseMap = new HashMap<String, Course>();
        if (courseList != null && courseList.size() > 0) {
            structureNameCourseMap = courseList.stream().collect(Collectors.toMap(Course::getStructureName, Function.identity()));
        }
        return structureNameCourseMap;
    }

    /**
     * 清理文本首尾空格
     *
     * @param studentExcelModel 表格数据
     */
    private void cleanBlank(StudentExcelModel studentExcelModel)
    {
        if (StringUtils.isNotBlank(studentExcelModel.getName())) {
            studentExcelModel.setName(studentExcelModel.getName().trim());
        }
        if (StringUtils.isNotBlank(studentExcelModel.getCourseName())) {
            studentExcelModel.setCourseName(studentExcelModel.getCourseName().trim());
        }
        if (StringUtils.isNotBlank(studentExcelModel.getIdCard())) {
            studentExcelModel.setIdCard(studentExcelModel.getIdCard().trim());
        }
        if (StringUtils.isNotBlank(studentExcelModel.getPhone())) {
            studentExcelModel.setPhone(studentExcelModel.getPhone().trim());
        }
    }

    /**
     * 科目名称转换为科目id
     * （结构化名称匹配）
     *
     * @param studentExcelModel 表格数据
     * @param courseIdNameMap
     */
    private void changeCourseNameToId(StudentExcelModel studentExcelModel, Map<String, List<Course>> courseIdNameMap)
    {
        //中文括号替换为英文
        if (studentExcelModel.getCourseName() != null) {
            studentExcelModel.setCourseName(studentExcelModel.getCourseName()
                    .replace("（", "(")
                    .replace("）", ")"));
        }
        //1.科目id
        if (courseIdNameMap.containsKey(studentExcelModel.getCourseName())) {
            List<Course> courses = courseIdNameMap.get(studentExcelModel.getCourseName());
            studentExcelModel.setCourseId(courses.get(0).getId());
        }
    }

    /**
     * 检查数据正确性
     * 必填项(身份证号码、学员姓名、科目),表格中身份证号码是否存在
     *
     * @param studentExcelModel 表格数据
     * @param idCardListInExcl  表格中的身份证号集合
     * @param students          正确的学生数据集合
     * @param studentCourseList 学员科目集合
     * @param excelImportErrorDataList      错误的学生数据集合
     * @param count             表格序号
     */
    private void checkStudentDataRight(StudentExcelModel studentExcelModel,
                                       List<String> idCardListInExcl,
                                       List<Student> students,
                                       List<StudentCourse> studentCourseList,
                                       List<ExcelImportErrorData> excelImportErrorDataList,
                                       int count)
    {
        //验证必填项
        if (StringUtils.isEmpty(studentExcelModel.getIdCard())) {
            setErrorInfo(studentExcelModel, count, "身份证号码未填写", excelImportErrorDataList);
            return;
        }
        if (studentExcelModel.getIdCard().length() != StudentConst.ID_CARD_DIGIT) {
            setErrorInfo(studentExcelModel, count, "身份证号码位数不正确", excelImportErrorDataList);
            return;
        }
        if (StringUtils.isEmpty(studentExcelModel.getName())) {
            setErrorInfo(studentExcelModel, count, "学员姓名未填写", excelImportErrorDataList);
            return;
        }
        if (studentExcelModel.getCourseId() == null) {
            setErrorInfo(studentExcelModel, count, "所选科目不存在或已禁用！", excelImportErrorDataList);
            return;
        }
        if (StringUtils.isEmpty(studentExcelModel.getCourseName())) {
            setErrorInfo(studentExcelModel, count, "科目未填写", excelImportErrorDataList);
            return;
        }
        //验证表格中身份证是否相同
        boolean a = checkIdCardInExcl(studentExcelModel, count, idCardListInExcl, excelImportErrorDataList);
        if (!a) {
            return;
        }
        //验证是否有名字不同但身份证相同的情况出现
        boolean b = checkDifferentNameSameIdCard(studentExcelModel, studentCourseList, excelImportErrorDataList, count);
        if (!b) {
            return;
        }
        //验证数据库中同科目中身份证是否相同
        boolean c = checkIdCardInDb(studentExcelModel, studentCourseList, excelImportErrorDataList, count);
        if (!c) {
            return;
        }
        //数据正确
        Student student = new Student();
        BeanUtil.copyProperties(studentExcelModel, student);
        student.setStructureName(studentExcelModel.getCourseName());
        student.setCourseId(studentExcelModel.getCourseId());
        student.setRemark(studentExcelModel.getRemark());
        students.add(student);
    }

    /**
     * 设置错误信息
     *
     * @param studentExcelModel 表格数据
     * @param count             表格序号
     * @param message           错误描述
     */
    private void setErrorInfo(StudentExcelModel studentExcelModel, int count, String message, List<ExcelImportErrorData> excelImportErrorDataList)
    {
        ExcelImportErrorData<StudentExcelModel> excelImportErrorData = new ExcelImportErrorData();
        excelImportErrorData.setData(studentExcelModel);
        excelImportErrorData.setOrderNum(count);
        excelImportErrorData.setMessage(message);
        excelImportErrorDataList.add(excelImportErrorData);
    }

    /**
     * 检查表格中身份证号码是否相同
     *
     * @param studentExcelModel 表格数据
     * @param count             表格序号
     * @param idCardListInExcl  身份证+科目 集合
     * @param excelImportErrorDataList      错误
     * @return boolean true不重复 false有重复
     */
    private boolean checkIdCardInExcl(StudentExcelModel studentExcelModel,
                                      int count,
                                      List<String> idCardListInExcl,
                                      List<ExcelImportErrorData> excelImportErrorDataList)
    {
        String idCard = studentExcelModel.getIdCard();
        String courseName = studentExcelModel.getCourseName();
        if (idCardListInExcl.contains(idCard + "-" + courseName)) {
            setErrorInfo(studentExcelModel, count, "表格中身份证号码重复", excelImportErrorDataList);
            return false;
        } else {
            idCardListInExcl.add(idCard + "-" + courseName);
            return true;
        }
    }

    /**
     * 验证是否有名字不同但身份证相同的情况出现
     *
     * @param studentExcelModel 表格数据
     * @param excelImportErrorDataList      错误
     * @param countNum          表格序号
     * @return
     */
    private boolean checkDifferentNameSameIdCard(StudentExcelModel studentExcelModel,
                                                 List<StudentCourse> studentCourseList,
                                                 List<ExcelImportErrorData> excelImportErrorDataList,
                                                 int countNum)
    {
        if (studentCourseList == null || studentCourseList.size() == 0) {
            return true;
        }
        boolean b = studentCourseList.stream()
                .anyMatch(o -> o.getIdCard().equals(studentExcelModel.getIdCard()) && !o.getStudentName().equals(studentExcelModel.getName()));
        if (b) {
            setErrorInfo(studentExcelModel, countNum, "存在姓名不相同身份证重复情况！", excelImportErrorDataList);
            return false;
        } else {
            return true;
        }
    }

    /**
     * 检查数据库同科目中身份证号码是否相同
     *
     * @param studentExcelModel 表格数据
     * @param studentCourseList 学院科目
     * @param excelImportErrorDataList      错误
     * @param countNum          表格序号
     * @return
     */
    private boolean checkIdCardInDb(StudentExcelModel studentExcelModel,
                                    List<StudentCourse> studentCourseList,
                                    List<ExcelImportErrorData> excelImportErrorDataList,
                                    int countNum)
    {
        if (studentCourseList == null || studentCourseList.size() == 0) {
            return true;
        }
        boolean flag = studentCourseList.stream()
                .anyMatch(o -> o.getIdCard().equals(studentExcelModel.getIdCard()) && o.getCourseId().equals(studentExcelModel.getCourseId()));
        if (flag) {
            setErrorInfo(studentExcelModel, countNum, "同科目已存在相同身份证号码！", excelImportErrorDataList);
            return false;
        } else {
            return true;
        }
    }

    /**
     * 给正确数据补充信息 创建人、科目转换为id等
     *
     * @param students 正确数据
     */
    private void applyStudentData(List<Student> students)
    {
        if (students.size() > 0) {
            //获取操作机构
            Long createInsId = getInstitution();
            Long userId = SecurityUtils.getUserId();
            //获取批次
            StudentBatch newBatchOnDay = getNewBatchOnDay(createInsId);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("遍历赋值开始 " + df.format(new Date()));
            System.out.println("学员数量：" + students.size());
            for (Student student : students) {
                //1.批次
                student.setBatchId(newBatchOnDay.getId());
                //2.创建人id
                student.setCreateBy(userId);
                //3.状态
                student.setStatus(StudentConst.AuditCode.STATUS_NO_CHECK.getCode());
                //4.关联机构id
                student.setInsId(createInsId);
            }
            System.out.println("遍历赋值结束 " + df.format(new Date()));
        }
    }

    /**
     * 获取批次、机构等信息
     *
     * @return
     */
    private Student getStudentInfo()
    {
        //获取操作机构
        Long createInsId = getInstitution();
        Long userId = SecurityUtils.getUserId();
        //获取批次
        StudentBatch newBatchOnDay = getNewBatchOnDay(createInsId);
        Student student = new Student();
        //1.批次
        student.setBatchId(newBatchOnDay.getId());
        //2.创建人id
        student.setCreateBy(userId);
        //3.状态
        student.setStatus(StudentConst.AuditCode.STATUS_NO_CHECK.getCode());
        //4.关联机构id
        student.setInsId(createInsId);
        return student;
    }

    /**
     * 获取导入操作的机构，如果是管理员导入，那就属于默认机构
     *
     * @return
     */
    private Long getInstitution()
    {
        Long createId = null;
        Long currentId = SecurityUtils.getUserId();
        //创建人，如果创建人是admin，那么创建人更改为默认机构
        if (SysUser.isAdmin(currentId)) {
            List<SysUser> sysUsers = userMapper.selectUserByCondition(new SysUser().setDefaultFlag(1));
            createId = sysUsers.size() > 0 ? sysUsers.get(0).getUserId() : currentId;
        } else {
            createId = currentId;
        }
        return createId;
    }

    /**
     * 获取当天的批次号
     *
     * @return
     */
    private StudentBatch getNewBatchOnDay(Long createInsId)
    {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String nowDate = dateFormat.format(new Date());
        String batchNum = null;
        //处理批次
        List<StudentBatch> studentBatches = batchService.getBaseMapper().selectList(Wrappers.<StudentBatch>lambdaQuery()
                .likeRight(StudentBatch::getBatchNum, nowDate)
                .orderByDesc(StudentBatch::getCreateTime));
        if (studentBatches.size() == 0) {
            batchNum = nowDate + "001";
        } else {
            String substring = studentBatches.get(0).getBatchNum().substring(8);
            Integer newBatchIntNum = Integer.parseInt(substring) + 1;
            //判断是否需要补位
            String newBatchNum = String.valueOf(newBatchIntNum);
            if (newBatchNum.length() < StudentBatchConst.COVERAGE) {
                int n = StudentBatchConst.COVERAGE - newBatchNum.length();
                for (int i = 0; i < n; i++) {
                    newBatchNum = "0" + newBatchNum;
                }
            }
            batchNum = nowDate + newBatchNum;
        }
        StudentBatch studentBatch = new StudentBatch();
        studentBatch.setBatchNum(batchNum);
        studentBatch.setPayFlag(0L);
        studentBatch.setStatus(StudentBatchConst.AuditCode.NO_CHECK.getCode());
        studentBatch.setInsId(createInsId);
        batchService.getBaseMapper().insert(studentBatch);
        return studentBatch;
    }

    /**
     * 保存学员数据，包括相关联的数据
     *
     * @param studentReqList 表格数据
     */
    private void saveStudentInfo(List<Student> studentReqList)
    {
        if (CollectionUtil.isEmpty(studentReqList)) {
            return;
        }

        List<String> idCardList = studentReqList.stream().map(Student::getIdCard).collect(Collectors.toList());
        //只查id
        StudentDo studentDo = new StudentDo();
        studentDo.setIdCardList(idCardList);
        //只查id
        List<Student> studentPoList = studentService.listStudentPoByDo(studentDo);

        Map<String, Student> studentPoMapByIdCard = studentPoList.stream()
                .collect(Collectors.groupingBy(Student::getIdCard,
                        Collectors.collectingAndThen(Collectors.toList(),
                                CollectionUtil::getFirst)));

        //新增的学员student
        Student studentInfo = getStudentInfo();
        List<Student> newStudentList = new ArrayList<>();
        for (Student studentReq : studentReqList) {
            if (!studentPoMapByIdCard.containsKey(studentReq.getIdCard()) || studentPoList.size() == 0) {
                studentReq.setBatchId(studentInfo.getBatchId());
                studentReq.setCreateBy(studentInfo.getCreateBy());
                studentReq.setStatus(studentInfo.getStatus());
                newStudentList.add(studentReq);
            } else {
                studentReq.setId(studentPoMapByIdCard.get(studentReq.getIdCard()).getId());
            }
        }

        if (CollectionUtil.isNotEmpty(newStudentList)) {
            StudentUtils.batchEncryptPassword(newStudentList);
            studentService.saveBatch(newStudentList);
        }

        List<StudentCourse> studentCourseDoList = new ArrayList<>();

        for (Student studentReq : studentReqList) {
            StudentCourse studentCourse = new StudentCourse();
            studentCourse.setBatchId(studentInfo.getBatchId());
            studentCourse.setEntId(studentInfo.getEntId());
            studentCourse.setStatus(StudentConst.AuditCode.STATUS_NO_CHECK.getCode());
            studentCourse.setLineDate(studentInfo.getLineDate());
            studentCourse.setInsId(studentInfo.getInsId());
            studentCourse.setStudentId(studentReq.getId());
            studentCourse.setCourseId(studentReq.getCourseId());
            studentCourse.setRemark(studentReq.getRemark());
            studentCourseDoList.add(studentCourse);
        }

        if (CollectionUtil.isNotEmpty(studentCourseDoList)) {
            //判断同科目是否有已过期的
            studentCourseService.saveBatch(studentCourseDoList);
        }
    }

    /**
     * 批量指定企业
     *
     * @param studentVo
     */
    @Override
    public boolean batchSetEnt(StudentDto studentVo)
    {
        List<Long> idList = studentVo.getIdList();
        if (idList.size() == 0) {
            throw new GlobalException("未选择学员！");
        }
        LambdaUpdateWrapper<StudentCourse> update = new LambdaUpdateWrapper<StudentCourse>(StudentCourse.class);
        update.set(StudentCourse::getEntId, studentVo.getEntId())
                .in(StudentCourse::getId, idList);
        return studentCourseService.update(update);
    }

    /**
     * 检查过期的学生，并将其状态改为已过期
     */
    @Override
    public void checkStudentLineDate()
    {
        List<StudentCourse> list = studentCourseService.list(Wrappers.<StudentCourse>lambdaQuery()
                .ne(StudentCourse::getStatus, "3")
                // < 小于
                .lt(StudentCourse::getLineDate, DateUtil.beginOfDay(new Date())));
        if (list != null && list.size() > 0) {
            List<Long> idList = list.stream().map(StudentCourse::getId).collect(Collectors.toList());
            studentCourseService.updateBatchStatusByIdList(idList, StudentConst.AuditCode.STATUS_OUT_TIME.getCode());
        }
    }

    /**
     * 生成科目的信息二维码
     *
     * @param course   科目信息
     * @param response response
     */
    @Override
    public void createCourseQr(CourseReq course, HttpServletResponse response)
    {
        String courseJson = JSONObject.toJSONString(course);
        QrUtils.generate(courseJson, 300, 300, 10, response);
    }
}
